import 'dart:convert';

import 'package:flutter_provider_demo/commons/result.dart';
import 'package:shared_preferences/shared_preferences.dart';

enum SharedKey {
  user,
  catalogs,
  darkMode,
  language,
}

class SharedPreference {
  SharedPreference._() {
    final keys = SharedKey.values.map((SharedKey key) => key.name).toSet();
    _sharedPreferencesFuture = SharedPreferencesWithCache.create(
        cacheOptions: SharedPreferencesWithCacheOptions(
      allowList: <String>{...keys},
    ));
  }
  late final Future<SharedPreferencesWithCache> _sharedPreferencesFuture;

  static final SharedPreference _instance = SharedPreference._();
  factory SharedPreference() => _instance;

  Future<Result<void>> setString(SharedKey key, String value) async {
    try {
      final sharedPreferences = await _sharedPreferencesFuture;
      await sharedPreferences.setString(key.name, value);
      return Result.ok(null);
    } on Exception catch (e) {
      return Result.error(e);
    }
  }

  Future<Result<String?>> getString(SharedKey key) async {
    try {
      final sharedPreferences = await _sharedPreferencesFuture;
      String? r = sharedPreferences.getString(key.name);
      return Result.ok(r);
    } on Exception catch (e) {
      return Result.error(e);
    }
  }

  Future<Result<void>> delete(SharedKey key) async {
    try {
      final sharedPreferences = await _sharedPreferencesFuture;
      await sharedPreferences.remove(key.name);
      return Result.ok(null);
    } on Exception catch (e) {
      return Result.error(e);
    }
  }

  Future<Result<void>> setJson(SharedKey key, Map<String, dynamic> value) async {
    return setString(key, jsonEncode(value));
  }

  Future<Result<Map<String, dynamic>?>> getJson(SharedKey key) async {
    final value = await getString(key);
    if (value is Error) {
      return Result.error((value as Error).error);
    }
    try {
      final r = jsonDecode((value as Ok<String?>).value ?? '') as Map<String, dynamic>;
      return Result.ok(r);
    } on Exception catch (e) {
      return Result.error(e);
    }
  }

  Future<Result<void>> setBool(SharedKey key, bool value) async {
    try {
      final sharedPreferences = await _sharedPreferencesFuture;
      await sharedPreferences.setBool(key.name, value);
      return Result.ok(null);
    } on Exception catch (e) {
      return Result.error(e);
    }
  }
  Future<Result<bool?>> getBool(SharedKey key) async {
    try {
      final sharedPreferences = await _sharedPreferencesFuture;
      bool? r = sharedPreferences.getBool(key.name);
      return Result.ok(r);
    } on Exception catch (e) {
      return Result.error(e);
    }
  }
}
